/**
  ******************************************************************************
  * @author     Chris
  * @since      2024/6/15 17:37
  *
  * @file       hd_motor.c
  * @brief      Motor hardware driver.
  *
  * @note       This file contains the hardware driver for the Motor.
  *
  * @warning    None.
  ******************************************************************************
  * Change Logs:
  *   Date          Author       Notes
  *   2024/6/15     Chris        the first version
  *
  ******************************************************************************
  */


#include "hd_motor.h"


/**
 * @brief   直流电机初始化（使用 TIM15_CH1）
 *
 * @note    TB6612 直流电机控制芯片，PWMx 输入 PWM 信号，xIN1、xIN2 控制电机正反转。
 * @param   无
 * @retval  无
 */
static void Motor_init(Motor *this) {
    // AIN1 and AIN2 init
    this->in1GPIO->init(this->in1GPIO);
    this->in2GPIO->init(this->in2GPIO);
}

/**
 * @brief   直流电机速度控制
 *
 * @note    --------------------------------------------------
 *          | IN1 | IN2 | PWM | STBY |  O1 |  O2 | Status |
 *          |-----|-----|-----|------|-----|-----|--------|
 *          |  H  |  H  | H/L |  H   |  L  |  L  |  Wait  |
 *          |  L  |  H  |  H  |  H   |  L  |  H  | Invert |
 *          |  L  |  H  |  L  |  H   |  L  |  L  |  Wait  |
 *          |  H  |  L  |  H  |  H   |  H  |  L  |  Run   |
 *          |  H  |  L  |  L  |  H   |  L  |  L  |  Wait  |
 *          |  L  |  L  |  H  |  H   |    OFF    |  Stop  |
 *          | H/L | H/L | H/L |  L   |    OFF    |  STBY  |
 * @param   speed 直流电机速度。取值范围为 -100~100
 * @retval  无
 */
static void Motor_setSpeed(Motor *this, int8_t speed) {
    if (speed >= 0) {
        this->in1GPIO->setBit(this->in1GPIO);
        this->in2GPIO->resetBit(this->in2GPIO);
        this->timerPwm->timerOC->setCCR(this->timerPwm->timerOC,
                                        this->timerPwm->timerOC->timerChannel->channels[0], speed);
    } else {
        this->in1GPIO->resetBit(this->in1GPIO);
        this->in2GPIO->setBit(this->in2GPIO);
        this->timerPwm->timerOC->setCCR(this->timerPwm->timerOC,
                                        this->timerPwm->timerOC->timerChannel->channels[0], -speed);
    }
}

/**
 * @brief   运动
 *
 * @note
 * @param   speed 直流电机速度。取值范围为 -100~100
 * @retval  无
 */
static void Motor_start(Motor *this) {
    this->setSpeed(this, this->speed);
}

/**
 * @brief   运动
 *
 * @note
 * @param   speed 直流电机速度。取值范围为 -100~100
 * @retval  无
 */
static void Motor_stop(Motor *this) {
    this->setSpeed(this, 0);
}

static Motor *build(TimerPWM *timerPwm, GPIO *in1GPIO, GPIO *in2GPIO) {
    Motor *gpio = malloc(sizeof(Motor));

    Driver_add(gpio, GEN_PERM);

    gpio->timerPwm = timerPwm;
    gpio->in1GPIO  = in1GPIO;
    gpio->in2GPIO  = in2GPIO;
    gpio->speed    = 0;

    gpio->init     = &Motor_init;
    gpio->start    = &Motor_start;
    gpio->stop     = &Motor_stop;
    gpio->setSpeed = &Motor_setSpeed;

    return gpio;
}

const struct MotorClass MotorBuilder = {.build = &build};

